package pro.shushi.pamirs.hr.core.task;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.core.common.enmu.TimeUnitEnum;
import pro.shushi.pamirs.framework.connectors.data.sql.Pops;
import pro.shushi.pamirs.framework.connectors.data.sql.query.LambdaQueryWrapper;
import pro.shushi.pamirs.hr.api.enums.HrEmployeeStatusEnum;
import pro.shushi.pamirs.hr.api.model.org.Department;
import pro.shushi.pamirs.hr.api.model.org.Employee;
import pro.shushi.pamirs.hr.api.model.stat.DepartmentStaffStat;
import pro.shushi.pamirs.meta.annotation.Fun;
import pro.shushi.pamirs.meta.annotation.Function;
import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j;
import pro.shushi.pamirs.meta.domain.fun.FunctionDefinition;
import pro.shushi.pamirs.middleware.schedule.api.ScheduleAction;
import pro.shushi.pamirs.middleware.schedule.common.Result;
import pro.shushi.pamirs.middleware.schedule.domain.ScheduleItem;
import pro.shushi.pamirs.middleware.schedule.eunmeration.TaskType;
import pro.shushi.pamirs.trigger.enmu.TriggerTimeAnchorEnum;
import pro.shushi.pamirs.trigger.model.ScheduleTaskAction;
import pro.shushi.pamirs.trigger.service.ScheduleTaskActionService;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 异步任务参考：
 * https://doc.oinone.top/oio4/9286.html
 */
@Slf4j
@Component
@Fun(DepartmentStaffStatTask.FUN_NAMESPACE)
public class DepartmentStaffStatTask implements ScheduleAction {

    public static final String FUN_NAMESPACE = "hr.simple.service.DepartmentStaffStatTask";

    @Autowired
    private ScheduleTaskActionService scheduleTaskActionService;

    public void initTask() {
        ScheduleTaskAction taskAction = new ScheduleTaskAction();
        //定时任务描述
        taskAction.setDisplayName("部门人数统计异步任务");
        taskAction.setDescription("部门人数统计异步任务");
        //设置定时任务技术名
        taskAction.setTechnicalName(DepartmentStaffStat.MODEL_MODEL + "#" + DepartmentStaffStatTask.class.getSimpleName());
        //设置执行次数
        taskAction.setLimitExecuteNumber(-1);
        //设置执行周期规则
        taskAction.setPeriodTimeValue(10);
        taskAction.setPeriodTimeUnit(TimeUnitEnum.MINUTE);
        taskAction.setPeriodTimeAnchor(TriggerTimeAnchorEnum.START);
        //设置失败重试规则
        taskAction.setLimitRetryNumber(1);
        taskAction.setNextRetryTimeValue(1);
        taskAction.setNextRetryTimeUnit(TimeUnitEnum.MINUTE);
        //设置定时任务执行函数
        taskAction.setExecuteNamespace(FUN_NAMESPACE);
        taskAction.setExecuteFun("execute");
        //超时时间设置为5秒
        taskAction.setExecuteFunction(new FunctionDefinition().setTimeout(5000));
        taskAction.setTaskType(TaskType.BASE_SCHEDULE_TASK.getValue());
        //用户传递上下文参数
        taskAction.setContext(null);
        //定时任务是否生效
        taskAction.setActive(true);
        //第一次执行时间
        long firstExecuteTime = System.currentTimeMillis() + (3 * 60 * 1000);
        taskAction.setFirstExecuteTime(firstExecuteTime);
        //初始化任务,幂等可重复执行
        scheduleTaskActionService.submit(taskAction);
    }

    @Override
    public String getInterfaceName() {
        return FUN_NAMESPACE;
    }

    @Override
    @Function
    public Result<Void> execute(ScheduleItem item) {
        log.info("部门人员数量计算任务开始");
        long start = System.currentTimeMillis();
        List<Department> depts = new Department().queryList();
        if (CollectionUtils.isEmpty(depts)) {
            return new Result<>();
        }

        log.info("部门人员数量计算，部门数：" + depts.size());
        List<DepartmentStaffStat> deptStaffStats = new ArrayList<>();
        for (Department dept : depts) {
            LambdaQueryWrapper<Employee> employeeWrapper = Pops.<Employee>lambdaQuery().from(Employee.MODEL_MODEL).setBatchSize(-1)
                    .select(Employee::getEmployeeStatus, Employee::getDepartment)
                    .eq(Employee::getDepartmentCode, dept.getCode());
            List<Employee> employees = new Employee().queryList(employeeWrapper);
            Long turnStaffCount = 0L;
            Long entryStaffCount = 0L;
            Long quitStaffCount = 0L;
            if (CollectionUtils.isNotEmpty(employees)) {
                Map<HrEmployeeStatusEnum, Long> employeeStatusMap = employees.stream()
                        .collect(Collectors.groupingBy(Employee::getEmployeeStatus, Collectors.counting()));
                turnStaffCount = employeeStatusMap.getOrDefault(HrEmployeeStatusEnum.TRUN, 0L);
                entryStaffCount = employeeStatusMap.getOrDefault(HrEmployeeStatusEnum.ENTRY, 0L);
                quitStaffCount = employeeStatusMap.getOrDefault(HrEmployeeStatusEnum.QUITTED, 0L);
            }
            DepartmentStaffStat deptStaffStat = new DepartmentStaffStat();
            deptStaffStat.setDepartmentName(dept.getName());
            deptStaffStat.setDepartmentCode(dept.getCode());
            deptStaffStat.setTotalStaffCount(turnStaffCount + entryStaffCount + quitStaffCount);
            deptStaffStat.setStaffCount(turnStaffCount + entryStaffCount);
            deptStaffStat.setQuitStaffCount(quitStaffCount);
            deptStaffStats.add(deptStaffStat);

        }
        new DepartmentStaffStat().createOrUpdateBatch(deptStaffStats);
        log.info("部门人员数量计算, 总耗时："  + (System.currentTimeMillis()- start) + "ms");

        return new Result<>();
    }
}